home *** CD-ROM | disk | FTP | other *** search
- /*
- * alias.c - routines associated with Finder aliases
- */
-
- #include "RevRdist.h"
- #include <Aliases.h>
- #include <GestaltEqu.h>
-
- /*
- * My guess as to the internal structure of an alias
- * Apple reserves the right to change this
- */
-
- /*
- * Records after fixed part of alias
- */
- struct alias_part
- {
- Integer ap_type;
- Integer ap_size;
- /* Byte ap_data[ap_size rounded up to mult of 2]; */
- };
- typedef struct alias_part alias_part;
-
- /*
- * alias_part_type - deduced values for ap_type
- */
- enum alias_part_type
- {
- AL_PNAME = 0 /* parent folder name */
- ,AL_PLIST /* parent dirID list */
- ,AL_PATH /* full path */
- ,AL_DRIVER = 6 /* driver name (for CD ROM and ?) */
- ,AL_ASHARE = 9 /* volume mount info */
- };
-
- struct myalias
- {
- AliasRecord al_hdr; /* Apple header */
- Integer al_ver; /* alias version ? */
- Integer al_unk1;
- Str27 al_volname; /* volume name */
- unsigned long al_voldate; /* volume creation date */
- Integer al_voltype; /* volume type */
- FSSpec al_fs; /* file spec for orig file */
- Longint al_unk2; /* directory id ? */
- unsigned long al_unk3; /* a date of some kind */
- OSType al_type; /* file type */
- OSType al_creator; /* file creator */
- Integer al_unk4;
- Integer al_unk5;
- Integer al_unk6[8];
- alias_part al_p[1]; /* first one is always parent dir name */
- };
- typedef struct myalias myalias;
- typedef myalias *myaliasptr, **myaliashandle;
-
-
-
- /*
- *=========================================================================
- * update_alias (cn) - update alias information in Finder alias file
- * entry: cn = cnode for alias file on client
- * returns: OSErr for system errors
- * small + integer for internal failures
- *=========================================================================
- */
- OSErr
- update_alias (cnode_t *cn)
- {
- AliasHandle ah; /* handle to new alias */
- myaliasptr ap; /* ptr to original alias */
- alias_part *app; /* ptr to alias_part in alias */
- int c; /* char temp */
- int client; /* flag set to 0 if cannot be alias
- * to file on client */
- OSErr error;
- alias_part *fullp; /* ptr to full path part */
- Handle h; /* handle to original alias */
- int i, j; /* temp indexes */
- int len, flen; /* temp lengths */
- Longint lt; /* for gestalt() */
- Integer refnum; /* file ref num for alias file */
- size_t size; /* alias size */
- StringPtr src, dst; /* ptrs into full paths */
- CInfoPBRec ci;
- FSSpec fs; /* file spec for NewAlias */
- Str255 path; /* new full path */
- static int doAliases = -1; /* -1->don't know, 0->no, 1->yes */
-
- if (!doAliases)
- return 0;
- if (doAliases < 0)
- {
- lt = 0;
- error = Gestalt (gestaltAliasMgrAttr, <);
- if (error || !(lt & (1<<gestaltAliasMgrPresent)))
- {
- doAliases = 0;
- return 0;
- }
- else
- doAliases = 1;
- }
- Clue0 = "\pupdate_alias";
- Clue1 = "\pHOpenResFile";
- refnum = HOpenResFile (ClientVol, cn->parID, cn->name, fsRdWrPerm);
- if (refnum == -1)
- {
- error = ResError();
- if (error == 0)
- error = fnfErr;
- if (error == fnfErr && (Flags & PF_LISTONLY))
- error = 0;
- return error;
- }
- ah = 0;
- h = Get1Resource (rAliasType, 0);
- while (h) /* "while" so can "break" */
- {
- HLock (h);
- error = 1; /* not our kind of alias */
- ap = *((myaliashandle)h);
- /*
- * Since the internal structure of an alias is not
- * documented, we do some tests to detect changes
- * which might cause our code to fail.
- * We check:
- * * userType is 0, since that's what the Finder uses
- * * what we think is the version number is 2
- * * that there is nothing in the alias past the basic
- * stuff, since the Finder doesn't use any such
- * * the first alias_part is for the parent folder name
- */
- size = GetHandleSize(h);
- if (size < sizeof (*ap))
- break;
- if (ap->al_hdr.userType || ap->al_ver != 2
- || size != ap->al_hdr.aliasSize)
- break;
- app = ap->al_p;
- if (app->ap_type != AL_PNAME)
- break;
- /*
- * Now, scan through the alias_parts looking for any
- * entries which indicate the alias is not for a file
- * on the client volume.
- * If we find any non-client entries or if we don't
- * find a full path entry, we reject the alias.
- */
- client = 1;
- fullp = 0;
- while (client && app->ap_type >= 0)
- {
- len = app->ap_size;
- flen = len + (len & 1);
- switch (app->ap_type)
- {
- case AL_PNAME:
- case AL_PLIST:
- break;
- case AL_PATH:
- fullp = app;
- break;
- default:
- client = 0;
- break;
- }
- app = (alias_part *)((char *)app + sizeof(*app) + flen);
- }
- if (!client)
- break;
- if (!fullp)
- break;
- if ((len = fullp->ap_size) > 255)
- break;
- /*
- * See if the alias target exists as is
- * If so, no need to change alias.
- * We expect target to not exist. Any other
- * errors are a surprise.
- */
- src = (StringPtr)fullp + sizeof (*fullp) - 1;
- ZERO(ci);
- ci.hFileInfo.ioNamePtr = src;
- ci.hFileInfo.ioVRefNum = ClientVol;
- Clue1 = "\pPBGetCatInfo";
- error = PBGetCatInfo (&ci, false);
- if (error != fnfErr && error != nsvErr && error != dirNFErr)
- break;
- /*
- * Okay, take full path and replace the first part
- * (the volume name) with the client volume name.
- * If this file/folder exists, build a new alias
- * pointing to it.
- */
- COPYPS (ClientVolName, path);
- for (i = 1; i <= len; i++)
- if (src[i] == ':')
- break;
- dst = path + path[0];
- if (path[0] + (len - i) > 255)
- {
- error = 2; /* result path too long */
- break;
- }
- for ( ; i <= len; i++)
- {
- *++dst = c = src[i];
- if (c == ':' && i < len)
- j = i; /* j indexes start of last part */
- }
- path[0] = dst - path;
- ZERO(ci);
- ci.hFileInfo.ioNamePtr = path;
- ci.hFileInfo.ioVRefNum = ClientVol;
- error = PBGetCatInfo (&ci, false);
- if (error)
- {
- if (error == fnfErr || error == dirNFErr)
- error = 3;
- break;
- }
- fs.vRefNum = ClientVol;
- fs.parID = ci.hFileInfo.ioFlParID;
- flen = len - j;
- BlockMove (src + j + 1, fs.name + 1, flen);
- fs.name[0] = flen;
- Clue1 = "\pNewAlias";
- error = NewAlias (nil, &fs, &ah);
- if (error == 0 && ah == 0)
- error = 4;
- if (error)
- break;
- len = (*ah)->aliasSize;
- if (Flags & PF_VERBOSE)
- {
- notice (L_ALIAS, fs.name, nil);
- }
- if (!(Flags & PF_LISTONLY))
- {
- HUnlock (h);
- SetHandleSize (h, len);
- error = MemError();
- if (error)
- break;
- HLock (h);
- BlockMove ((Ptr)(*ah), (*h), len);
- ChangedResource (h);
- if (error = ResError())
- break;
- }
- break;
- }
- if (h)
- {
- HUnlock (h);
- ReleaseResource (h);
- }
- if (ah)
- DisposHandle ((Handle)ah);
- (void) CloseResFile (refnum);
- return error;
- }